package Android.SinYateClient;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;

import org.w3c.dom.Document;

import android.content.Context;

public class ClientDriver {
	private Communication cm;
	private String clientip;
	private String clientid;
	private String serveradres;
	private String port;
	private XMLParser xmlparser;
	private Thread threadObj;
	private int intervalpol;
	private boolean stop;
	private String testcampaignid;
	private ArrayList<Task> tasklist;
	private ArrayList<Task> finishedtasklist;
	private Task screenshottask;
	AndroidClient androidClient;

	public ClientDriver(String serveradres, String port, int intervalpol,
			String clientip, String clientid, AndroidClient androidClient) {
		cm = new Communication(serveradres, Integer.parseInt(port));
		xmlparser = new XMLParser();
		this.intervalpol = intervalpol;
		this.clientip = clientip;
		this.clientid = clientid;
		this.serveradres = serveradres;
		this.port = port;
		this.androidClient = androidClient;

		stop = false;
		finishedtasklist = new ArrayList<Task>();
		if (clientid.equals("0")) {
			register();
		}

		threadObj = new Thread(new heartbeat());
		threadObj.start();
	}

	public class heartbeat implements Runnable {

		@Override
		public void run() {

			System.out.println("run van heartbeat");

			while (!stop) {
				FileInputStream fin = null;
				try {
					fin = androidClient.openFileInput("sinyateconfig.txt");
				} catch (FileNotFoundException e) {
					e.printStackTrace();
				}
				InputStreamReader isr = new InputStreamReader(fin);
				BufferedReader br = new BufferedReader(isr);
				try {
					clientip = br.readLine();
					port = br.readLine();
					clientid = br.readLine();
					br.close();
					fin.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
				String xml = xmlparser.getPollingXML(clientid);
				String response = cm.sendPolling(clientid, xml);
				if (response != null && !response.equals("")) {
					// lazy evaluation !!!
					Assignment assign = xmlparser.getAssignment(response);
					executeTask(assign);
				}
				try {
					Thread.sleep(intervalpol * 1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}

			}
		}
	}

	/**
	 * Main task scheduler, executes the assignment described in the assignment
	 * class
	 */
	public void executeTask(Assignment assignment) {
		System.out.println("executeTask()");
		tasklist = assignment.getTaskList();
		testcampaignid = assignment.getTestId();
		// houdt bij of de vorige task een applicationopdracht was.
		boolean app = false;
		// houdt de laatste Application task bij, nodig om de info (url,...)
		// eruit te halen
		Task appTask = null;
		for (int i = 0; i < tasklist.size(); i++) {
			Task task = tasklist.get(i);
			String tasktype = task.getType();
			if (tasktype.equals("configuration")) {
				saveSettings(task);
				app = false;
			} else if (tasktype.equals("application")) {
				app = true;
				appTask = task;
			} else if (tasktype.equals("screenshot") && app) {
				onScreenshot(appTask, task);
				app = false;
			} else if (tasktype.equals("keystroke")) {
				onKeystroke(task);
				app = false;
			} else if (tasktype.equals("information")) {
				onInformation(task);
				app = false;
			} else {
				// wrong assignment
			}
		}

	}

	public void saveSettings(Task task) {
		FileOutputStream fOut = null;
		try {
			System.out.println(androidClient);

			fOut = androidClient.openFileOutput("sinyateconfig.txt",
					Context.MODE_WORLD_READABLE);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		OutputStreamWriter osw = new OutputStreamWriter(fOut);

		if (task.getParameterValue("server") != null) {
			serveradres = task.getParameterValue("server");

			try {
				osw.write(serveradres + "\r\n");

				if (task.getParameterValue("port") != null) {
					port = task.getParameterValue("task");
					osw.write(port + "\r\n");
				}
				if (task.getParameterValue("id") != null) {
					clientid = task.getParameterValue("id");
					osw.write(clientid + "\r\n");
				}
				if (task.getParameterValue("heartbeat") != null) {
					intervalpol = Integer.parseInt(task
							.getParameterValue("heartbeat"));
					osw.write(intervalpol + "\r\n");
				}

				osw.flush();
				osw.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			if (!testcampaignid.equals("0")) {
				onFinished(task);
			}
		}
	}

	public void onApplication(Task task) {
		String parameter = task.getParameterValue("parameter");
		if (task.getParameterValue("proxy") != null) {
			if (task.getParameterValue("proxy").equals("true")) {
				if (port.equals("80")) {
					parameter = "http://" + serveradres + "/proxyservlet?"
							+ "url=" + parameter + "&testid=" + testcampaignid
							+ "&taskid=" + task.getTaskId() + "&deviceid="
							+ clientid;
				} else {
					parameter = "http://" + serveradres + ":" + port
							+ "/proxyservlet?" + "url=" + parameter
							+ "&testid=" + testcampaignid + "&taskid="
							+ task.getTaskId() + "&deviceid=" + clientid;
				}
			}
		}
		// Aan te vullen later

		onFinished(task);

	}

	public void onScreenshot(Task app, Task task) {
		androidClient.browserScreenshot(app, task);
	}

	public void onKeystroke(Task task) {
		onFinished(task);
	}

	public void onInformation(Task task) {
		onFinished(task);
	}

	public void onFinished(Task task) {
		finishedtasklist.add(task);
		if (finishedtasklist.size() == tasklist.size()) {
			String xml = xmlparser.getConfirmationXML(clientid);
			cm.sendXML(clientid, testcampaignid, task.getTaskId() + "", xml);
			testcampaignid = "0";
			screenshottask = null;
			finishedtasklist = new ArrayList<Task>();
		}
	}

	public void register() {

		System.out.println("register()");

		Document doc = xmlparser.getRegistrationXML(androidClient);
		String xml = cm.register(XMLParser.provideXMLString(doc));
		if (!xml.equals("")) {
			Assignment assignment = xmlparser.getAssignment(xml);
			executeTask(assignment);
		}
	}

	public void stopServer() {
		stop = true;
		threadObj.stop();
	}

	public void sendImage(byte[] image, int id) {
		cm.sendImage(clientid, testcampaignid, id + "", image);
	}

}
